﻿using System;
using System.ComponentModel;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Extensibility;
using PostSharp.Reflection;

namespace BusinessFramework.AOP
{
    [Serializable]
    [IntroduceInterface(typeof(INotifyPropertyChanging), OverrideAction = InterfaceOverrideAction.Fail)]
    [MulticastAttributeUsage(MulticastTargets.Class, Inheritance = MulticastInheritance.Strict)]
    public sealed class ImplementNotifyPropertyChangingAttribute : InstanceLevelAspect, INotifyPropertyChanging
    {
        [IntroduceMember(Visibility = Visibility.Family, IsVirtual = true,
            OverrideAction = MemberOverrideAction.Fail)]
        public void OnPropertyChanging(PropertyChangingEventArgs e)
        {
            if (PropertyChanging != null)
                PropertyChanging(Instance, e);
        }

        [IntroduceMember(OverrideAction = MemberOverrideAction.Fail)]
        public event PropertyChangingEventHandler PropertyChanging;

        [ImportMember("OnPropertyChanging", IsRequired = true, Order = ImportMemberOrder.AfterIntroductions)]
        public Action<PropertyChangingEventArgs> OnPropertyChangingMethod;

        [OnLocationSetValueAdvice,
         MulticastPointcut(Targets = MulticastTargets.Property, Attributes = MulticastAttributes.Instance | MulticastAttributes.NonAbstract)]
        public void OnPropertySet(LocationInterceptionArgs args)
        {
            OnPropertyChangingMethod(new PropertyChangingEventArgs(args.Location.Name));

            // Actually sets the value.
            args.ProceedSetValue();
        }
    }
}